package com.netty.websocket;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.netty.utils.Constants;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.handler.codec.http.*;
import io.netty.handler.codec.http.websocketx.*;
import io.netty.util.CharsetUtil;
import io.netty.util.internal.StringUtil;

import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

public class MyWebSocketServerHandler extends SimpleChannelInboundHandler<Object> {
    private WebSocketServerHandshaker handshaker;

    private String ip;

    private Integer port;


    public MyWebSocketServerHandler(String ip,Integer port){
        this.ip=ip;
        this.port=port;
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("客户端与服务器段开启");
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        Global.group.remove(ctx.channel());
        HashMap<String, Channel> userChannel = Global.userChannel;
        List<String> collect = userChannel.entrySet().stream().map(entry -> {
            if (entry.getValue().equals(ctx.channel())) {
                return entry.getKey();
            }
            return null;
        }).filter(str -> {
            return !StringUtil.isNullOrEmpty(str);
        }).collect(Collectors.toList());
        if(collect.size()>0){
            String key = collect.get(0);
            Global.userChannel.remove(key);
        }
        System.out.println("客户端与服务器链接关闭！");
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Object frame)
            throws Exception {
        if (frame instanceof FullHttpRequest) {
            //握手
            handleHttpRequest(ctx, ((FullHttpRequest) frame));
        }else if(frame instanceof TextWebSocketFrame){

        }
        else if (frame instanceof BinaryWebSocketFrame) {
        }
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }


    private void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest req) {

        if (!req.decoderResult().isSuccess() ||
                !("websocket".equals(req.headers().get("Upgrade")))) {
            sendHttpResponse(ctx, req, new DefaultFullHttpResponse(
                    HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST));
            return;
        }

        //在这里根据uri绑定用户
        String uri = req.uri();
        String user=uri.replaceAll("/","");
        //用作群发
        Global.group.add(ctx.channel());
        //用作单独发送
        Global.userChannel.put(user,ctx.channel());


        // 构造握手响应返回
        WebSocketServerHandshakerFactory wsFactory
                = new WebSocketServerHandshakerFactory("ws://"+ ip+":"+ port+"/websocket", null,false);
        handshaker = wsFactory.newHandshaker(req);
        if (handshaker == null) {
            // 发送版本错误
            WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel());
        } else {
            // 握手响应
            handshaker.handshake(ctx.channel(), req);
        }


    }

    private void sendHttpResponse(ChannelHandlerContext ctx,
                                  FullHttpRequest req, DefaultFullHttpResponse res) {
        if (res.status().code() != 200) {
            ByteBuf buf = Unpooled.copiedBuffer(res.status().toString(),
                    CharsetUtil.UTF_8);
            res.content().writeBytes(buf);
            buf.release();
        }

        ChannelFuture future = ctx.channel().writeAndFlush(res);
        if (!isKeepAlive(req) || res.status().code() != 200) {
            future.addListener(ChannelFutureListener.CLOSE);
        }

    }

    private static boolean isKeepAlive(FullHttpRequest req) {
        return false;
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
            throws Exception {
        cause.printStackTrace();
        ctx.close();
    }

}